package com.lihaozhe.orderservice.service;

import com.lihaozhe.orderservice.util.LoadbalancerUtil;
import com.lihaozhe.productservice.dto.ProductDTO;
import com.lihaozhe.userservice.dto.UserDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 负载均衡服务类
 * 演示如何使用LoadBalancer进行服务调用和负载均衡
 *
 * @author 李昊哲
 * @version 1.0.0
 */
@Service
public class LoadBalancerService {

  private final LoadbalancerUtil loadbalancerUtil;
  private final Logger logger = LoggerFactory.getLogger(LoadBalancerService.class);

  /**
   * 构造函数，注入依赖
   */
  public LoadBalancerService(LoadbalancerUtil loadbalancerUtil) {
    this.loadbalancerUtil = loadbalancerUtil;
  }

  /**
   * 方式1：使用@LoadBalanced的RestClient进行服务调用（推荐）
   * 这种方式会自动进行负载均衡
   */
  public ProductDTO getProductWithLoadBalancer(Long productId) {
    // 注意：这里使用服务名而不是具体的URL
    // String url = "http://product-service/api/products/" + productId;
    String productServiceId = "product-service";
    String url = String.format("%s/api/products/%d", loadbalancerUtil.getCurrentServiceUrl(productServiceId), productId);

    try {
      // 定义泛型类型：Map<String, User>
      ParameterizedTypeReference<Map<String, Object>> typeRef = new ParameterizedTypeReference<Map<String, Object>>() {
      };
      Map<String, Object> response = loadbalancerUtil.getLoadBalancedRestClient().get()
          .uri(url)
          .retrieve()
          .body(typeRef);

      if (response != null && response.get("product") != null) {
        // 将Map转换为ProductDTO
        Map<String, Object> productMap = (Map<String, Object>) response.get("product");
        Map<String, Object> instanceInfo = (Map<String, Object>) response.get("instanceInfo");

        ProductDTO product = new ProductDTO();
        product.setId(Long.valueOf(productMap.get("id").toString()));
        product.setName((String) productMap.get("name"));
        product.setCategory((String) productMap.get("category"));
        product.setPrice(Double.valueOf(productMap.get("price").toString()));
        product.setStock(Integer.valueOf(productMap.get("stock").toString()));
        product.setDescription((String) productMap.get("description"));

        logger.info("通过负载均衡调用商品服务，实例信息: {}", instanceInfo);
        return product;
      }
      return null;
    } catch (Exception e) {
      throw new RuntimeException("通过负载均衡调用商品服务失败: " + e.getMessage());
    }
  }


  /**
   * 获取所有商品服务实例信息
   */
  public List<ServiceInstance> getProductServiceInstances() {
    return loadbalancerUtil.getDiscoveryClient("product-service");
  }

  /**
   * 获取当前选择的商品服务实例
   */
  public ServiceInstance getCurrentProductServiceInstance() {
    return loadbalancerUtil.getLoadBalancerClient().choose("product-service");
  }

  /**
   * 使用负载均衡调用用户服务
   */
  public UserDTO getUserWithLoadBalancer(Long userId) {
    // String url = "http://user-service/api/users/" + userId;
    String userServiceId = "user-service";
    String url = String.format("%s/api/users/%s", loadbalancerUtil.getCurrentServiceUrl(userServiceId), userId);

    try {
      return loadbalancerUtil.getLoadBalancedRestClient().get()
          .uri(url)
          .retrieve()
          .body(UserDTO.class);
    } catch (Exception e) {
      throw new RuntimeException("通过负载均衡调用用户服务失败: " + e.getMessage());
    }
  }

  /**
   * 测试负载均衡 - 连续调用多次观察分布
   */
  public Map<String, Object> testLoadBalancing(int callCount) {
    Map<String, Integer> distribution = new java.util.HashMap<>();
    List<Map<String,Object>> details = new ArrayList<>();
    String productServiceId = "product-service";

    for (int i = 0; i < callCount; i++) {
      // String url = "http://product-service/api/products/instance-info";
      String url = String.format("%s/api/products/instance-info", loadbalancerUtil.getCurrentServiceUrl(productServiceId));

      try {
        // 定义泛型类型：Map<String, Object>
        ParameterizedTypeReference<Map<String, Object>> typeRef = new ParameterizedTypeReference<Map<String, Object>>() {
        };
        Map<String, Object> response = loadbalancerUtil
            .getLoadBalancedRestClient()
            .get()
            .uri(url)
            .retrieve()
            .body(typeRef);

        if (response != null) {
          String instanceId = (String) response.get("instanceId");
          distribution.put(instanceId, distribution.getOrDefault(instanceId, 0) + 1);
          details.add(response);
        }

        // 短暂延迟，避免请求过快
        Thread.sleep(10);
      } catch (Exception e) {
        logger.error("负载均衡测试调用失败: {}", e.getMessage());
      }
    }

    return Map.of(
        "totalCalls", callCount,
        "distribution", distribution,
        "details", details,
        "instances", loadbalancerUtil.getDiscoveryClient(productServiceId).size()
    );
  }
}
